#ifndef MyStack_h // Защита от повторной компиляции
#define MyStack_h // Модуль подключен

#include <iostream>
#include <stdexcept>

namespace my_stack {
    // Функция для проверки, является ли число простым
    bool is_prime(int n) {
        if (n <= 1)
            return false;

        // Проверяем, делится ли число нацело на какое-либо число от 2 до sqrt(n)
        for (int i = 2; i * i <= n; ++i) {
            if (n % i == 0)
                return false;
        }
        return true;
    }

    // Шаблонный класс ListNode (узел односвязного списка)
    template <class T, class StackType>
    class ListNode {
    private:
        T data = T();           // Информационная часть узла
        ListNode* next = nullptr; // Указатель на следующий узел списка

        // Приватный конструктор узла
        ListNode(void) = default;

        friend StackType; // Дружественный класс MyStack
    };

    // Шаблонный класс MyStack на основе односвязного списка
    template <class T>
    class MyStack {
        typedef class ListNode<T, MyStack<T>> Node;
        Node* top;

    public:
        MyStack(void);      // Конструктор
        ~MyStack(void);     // Деструктор
        bool isEmpty(void); // Стек пустой?
        bool push(T element); // Добавить элемент в вершину стека
        bool pop(void);     // Удалить элемент из вершины стека
        T topElement(void); // Получить элемент из вершины стека
    };

    template <class T>
    MyStack<T>::MyStack() {
        top = nullptr;
    }

    template <class T>
    MyStack<T>::~MyStack() {
        while (!isEmpty()) {
            pop();
        }
    }

    template <class T>
    bool MyStack<T>::isEmpty(void) {
        return (top == nullptr);
    }

    template <class T>
    bool MyStack<T>::push(T element) {
        Node* newNode = new Node;
        if (!newNode) {
            return false; // Не удалось выделить память для нового узла
        }

        newNode->data = element;
        newNode->next = top;
        top = newNode;
        return true;
    }

    template <class T>
    bool MyStack<T>::pop(void) {
        if (isEmpty()) {
            return false; // Стек пустой, нельзя выполнять pop
        }

        Node* temp = top;
        top = top->next;
        delete temp;
        return true;
    }

    template <class T>
    T MyStack<T>::topElement(void) {
        if (isEmpty()) {
            // Здесь может быть обработка ошибки, например, выбрасывание исключения
            // Для целей этого примера, просто вернем значение по умолчанию
            return T();
        }
        return top->data;
    }

    // Функция для разложения числа на простые множители
    template <class DATA>
    void Multipliers(int n, MyStack<DATA> &stack) {
        int divisor = 2;
        while (n > 1) {
            if (n % divisor == 0) {
                stack.push(DATA(divisor));
                n /= divisor;
            } else {
                divisor++;
            }
        }
    }
}

#endif
